home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 3 / BBS in a box - Trilogy III.iso / Files / Prog / B-C / C++ FAQ Reference 1.0 / C++ FAQ Reference 1.0.rsrc / TEXT_1429.txt < prev    next >
Encoding:
Text File  |  1993-06-30  |  3.6 KB  |  49 lines

  1. Virtual data isn't strictly a 'part' of C++, however it can be simulated. It's not entirely pretty, but it works.  First we'll cover what it is and how to simulate it, then conclude with why it isn't 'part' of C++.
  2.  
  3. Consider classes Vec (like an array of int) and SVec (a stretchable Vec; ie: SVec overrides operator[] to automatically stretch the number of elements whenever a large index is encountered).  SVec inherits from Vec.  Naturally Vec's subscript operator is virtual.
  4.  
  5. Now consider a VStack class (Vec-based-Stack).  Naturally this Stack has a capacity limited by the fixed number of elements in the underlying Vec data structure.  Then someone comes along and wants an SVStack class (SVec based Stack).  For some reason, they don't want to merely modify VStack (say, because there are many users already using it).
  6.  
  7. The obvious choice then would be to inherit SVStack from VStack, however then there'd be *two* Vecs in an SVStack object (one explicitly in VStack, the other as the base class subobject in the SVec which is explicitly in the SVStack).  That's a lot of extra baggage.  There are at least 2 solns:
  8.  * break the is-a link between SVStack and VStack, text-copy the code from
  9.    VStack and manually change 'Vec' to 'SVec'.
  10.  * activate some sort of virtual data, so subclasses can change the    class of subobjects.
  11.  
  12. To effect virtual data, we need to change the Vec subobject from a physically contained subobject into a ptr pointing to a dynamically allocated subobject:
  13.  
  14. _____original_____        |_____to_support_virtual_data_____
  15. class VStack {                | class VStack {
  16. protected:                | protected:
  17.   Vec v;  //where data stored        |   Vec& v; //where data is stored
  18.   int sp; //stack pointer        |   int sp; //stack pointer
  19. public:                | public:
  20.   VStack(int cap=10)        |   VStack(int cap=10)
  21.     : v(cap), sp(0) { }        |     : v(*new Vec(cap)), sp(0) { } //FREESTORE
  22.   void push(int x) {v[sp++]=x;}    |   void push(int x) {v[sp++]=x;}   //no change
  23.   int  pop()  {return v[--sp];}    |   int  pop()  {return v[--sp];}   //no change
  24.   ~VStack() { }   //unnecessary    |   ~VStack() {delete &v;}          //NECESSARY
  25. };                | };
  26.  
  27. Now the subclass has a shot at overriding the defn of the object referred to as 'v'.  Ex: basically SVStack merely needs to bind a new SVec to 'v', rather than letting VStack bind the Vec.  However classes can only initialize their *own* subobjects in an init-list.  Even if I had used a ptr rather than a ref, VStack must be prevented from allocating its own 'Vec'.  The way we do this is to add another ctor to VStack that takes a Vec& and does *not* allocate a Vec:
  28.     class VStack {
  29.     protected:
  30.       VStack(Vec& vv) : v(vv), sp(0) { }    //'protected' constructor!
  31.     //...                    //(prevents public access)
  32.     };
  33.  
  34. That's all there is to it!  Now the subclass (SVStack) can be defined as:
  35.     class SVStack : public VStack {
  36.     public:
  37.       SVStack(int init_cap=10) : VStack(*new SVec(init_cap)) { }
  38.     };
  39.  
  40. Pros:    * implementation of SVStack is a one-liner
  41.     * SVStack shares code with VStack
  42.  
  43. Cons:    * extra layer of indirection to access the Vec
  44.     * extra freestore allocations (both new and delete)
  45.     * extra dynamic binding (reason given in next question)
  46.  
  47. We succeeded at making *our* job easier as implementor of SVStack, but all clients pay for it.  It wouldn't be so bad if clients of SVStack paid for it, after all, they chose to use SVStack (you pay for it if you use it).  However the 'optimization' made the users of the plain VStack pay as well!
  48.  
  49. See the question after the next to find out how much the client's 'pay'.  Also: *PLEASE* read the few questions that follow the next one too (YOU WILL NOT GET A BALANCED PERSPECTIVE WITHOUT THE OTHERS).